﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SIA.Configurators;
using System.Net.Sockets;

namespace SIA.HwAccess.PLCSiemens.ConnectionDriver
{
    public class TCPWriteConnection : TCPClientConnection
    {
        protected CompactHwAddressCollection _writeAddressCollection = new CompactHwAddressCollection();
        private CompactHwAddressCollection editWriteHwAddressCollection = new CompactHwAddressCollection();

        public TCPWriteConnection(IDictionaryProperty ConnectionProperty, IDictionaryProperty signalsProperty)
            : base(ConnectionProperty, signalsProperty)
        {
            foreach (IDictionaryProperty tagP in signalsProperty.Values)
                  if (tagP["CONNESSIONE"].PropertyValue == ConnectionProperty["NOME"].PropertyValue)
                    _writeAddressCollection.Add(new S7HwAddress(tagP["INDIRIZZO"].PropertyValue).Round2Word());

            //Inizializzo Dati Da scrivere
            initWriteData();             
        }
        private void initWriteData()
        {
            foreach (IHwAddress hwAddress in _writeAddressCollection)
            {
                if (!_rawData.ContainsKey(hwAddress.DataKey))
                    _rawData.Add(hwAddress.DataKey, new Byte[4096]);
                if (_rawData[hwAddress.DataKey].Length < (hwAddress.StartByte + hwAddress.LenByte))
                    _rawData[hwAddress.DataKey] = new Byte[4096];
            }
        }

        public override void requestWriteData(IHwAddress address, int offset, byte value)
        {
            base.requestWriteData(address, offset, value);
            editWriteHwAddressCollection.Add( (new S7HwAddress(address)).Round2Word() );
        }

        public override void update()
        {
            if (_socket == null || !_socket.Connected) connect();
            if (_socket == null || !_socket.Connected) _status = eConnectionStatus.ERROR;
            
            foreach (IHwAddress hwa in _writeAddressCollection)
            {
                if (!_rawData.ContainsKey(hwa.DataKey))
                    _rawData.Add(hwa.DataKey, new Byte[4096]);
                if (_rawData[hwa.DataKey].Length < hwa.LenByte + hwa.StartByte)
                    _rawData[hwa.DataKey] = new Byte[4096];
            }

            if (editWriteHwAddressCollection.Count > 0)
            {
                SIA.Messages.MessageManager.sendMessage(this, "Write data: " + editWriteHwAddressCollection.ToString(), SIA.Messages.eMessageType.DEBUG);

                foreach (IHwAddress hwa in editWriteHwAddressCollection)
                    writeRawData(hwa);

                SIA.Messages.MessageManager.sendMessage(this, "Data wrote", SIA.Messages.eMessageType.DEBUG);
            }
            editWriteHwAddressCollection.Clear();

        }

       
        private void writeRawData(IHwAddress hwAddress)
        {            
            //Dati da inviare al PLC
            Byte[] sendData = new Byte[hwAddress.LenByte];
            for (int i = 0; i < hwAddress.LenByte; i++)
                sendData[i] = _rawData[hwAddress.DataKey][hwAddress.StartByte + i];


            //Recupero l'header e costruisco il pacchetto
            List<Byte> writeBuffer = new List<Byte>();
            writeBuffer.AddRange(S7Metods.GetHeaderWrite((byte)hwAddress.DataBlock, hwAddress.StartByte, hwAddress.LenByte / 2));
            writeBuffer.AddRange(sendData);
            //Invio richiesta
            _socket.Send(writeBuffer.ToArray(), SocketFlags.None);

            // Recive Data              //+16 me tengo largo
            Byte[] bytesReceived = new Byte[S7Metods.WriteResponse.Length + 16];
            int bytes = _socket.Receive(bytesReceived);

            //Controllo messaggio di conferma
            for (int i = 0; i < S7Metods.WriteResponse.Length; i++)
                if (S7Metods.WriteResponse[i] != bytesReceived[i])
                {
                    SIA.Messages.MessageManager.sendMessage(this, "S7Socket.writeData: Ritornato messaggio di errore, dati non scritti. ID:" + bytesReceived[8], SIA.Messages.eMessageType.DEBUG);
                    throw new Exception("S7Socket.writeData: Ritornato messaggio di errore, dati non scritti. ID:" + bytesReceived[8]);
                }
        }

        /// <summary>Registro un nuovo segnale</summary>
        /// <param name="signal"></param>
        public override void register(IHwSignal signal)
        {
            if (signal is S7Signal)
                if (!_signals.ContainsKey(signal.Name))
                {
                    IHwAddress ha = ((S7Signal)signal).Address;
                    _signals.Add(signal.Name, signal);
                    _writeAddressCollection.Add(((S7HwAddress)ha).Round2Word());
                    if (!_rawData.ContainsKey(ha.DataKey))
                        _rawData.Add(ha.DataKey, new Byte[4096]);
                    if (_rawData[ha.DataKey].Length < (ha.StartByte + ha.LenByte))
                        _rawData[ha.DataKey] = new Byte[4096];
                    signal.Connection = this;                   
                }
        }

        new public String ToString()
        {
            return base.ToString() + " " + _info + " Interval: " + _timer.Interval;
        }

    }

}
